package libgin

import (
	"errors"
	"net/http"
	"reflect"
	"strings"

	"github.com/gin-gonic/gin"

	"gitee.com/goframe/lt-collector/libs/orma"
)

type Request struct {
	bean, result interface{}

	queryAnd []string
}

func (q *Request) request(c *gin.Context) {
	bean := &Request{
		bean:     reflect.New(reflect.Indirect(reflect.ValueOf(q.bean)).Type()).Interface(),
		queryAnd: q.queryAnd,
	}
	var err error
	switch c.Request.Method {
	case GET:
		err = bean.get(c)
	case POST:
		err = bean.post(c)
	case PUT:
		err = bean.put(c)
	case DELETE:
		err = bean.delete(c)
	default:
		Return.GinSet(c, http.StatusMethodNotAllowed, "")
		return
	}
	if err != nil {
		_ = c.Error(err)
		return
	}
	Return.GinOK(c, bean.result)
}

//从过滤器中获取绑定对象
func (q *Request) bind(c *gin.Context) error {
	bean, has := c.Get("BindBean")
	if !has {
		return c.ShouldBind(q.bean)
	}
	q.bean = bean
	return nil
}

func (q *Request) post(c *gin.Context) (err error) {
	if err = q.bind(c); err != nil {
		return
	}
	err = orma.NormalInsert(orma.GetEngine().InsertOne(q.bean))
	if err == orma.ErrOrmZeroResult {
		err = errors.New("插入数据失败,请检查输入内容")
	}
	if err != nil && strings.Contains(err.Error(), "Duplicate") {
		err = errors.New("插入数据失败,重复的主键")
	}
	if tableBean, ok := q.bean.(orma.TableWithPassword); ok {
		tableBean.SetPassword("")
		q.bean = tableBean
	}
	q.result = q.bean
	return
}

func (q *Request) checkIDExists() (idVal int64, err error) {
	//get bean address,not a pointer
	beanVal := reflect.Indirect(reflect.ValueOf(q.bean))
	idVal = beanVal.FieldByName("ID").Int()
	if idVal == 0 {
		err = errors.New("更新对象参数错误,请检查是否包含id字段")
	}
	return
}

func (q *Request) put(c *gin.Context) (err error) {
	if err = q.bind(c); err != nil {
		return
	}
	idVal, er := q.checkIDExists()
	if er != nil {
		return er
	}
	updateSn := orma.GetEngine().ID(idVal).UseBool().ForUpdate()
	err = orma.NormalUpdate(updateSn.Update(q.bean))
	if err == orma.ErrOrmNotModified {
		err = errors.New("更新数据失败,请刷新页面重试")
	}
	if tableBean, ok := q.bean.(orma.TableWithPassword); ok {
		tableBean.SetPassword("")
		q.bean = tableBean
	}
	q.result = q.bean
	return
}

func (q *Request) delete(c *gin.Context) (err error) {
	if err = q.bind(c); err != nil {
		return
	}
	idVal, er := q.checkIDExists()
	if er != nil {
		return er
	}
	err = orma.NormalInsert(orma.GetEngine().ID(idVal).Unscoped().NoAutoCondition().Delete(q.bean))
	if err == orma.ErrOrmZeroResult {
		err = errors.New("删除数据失败,请检查输入内容")
	}
	q.result = "删除数据完成"
	return
}

func (q *Request) get(c *gin.Context) (err error) {
	qb := new(orma.QueryBean)
	if err = c.Bind(qb); err != nil {
		return
	}
	res := orma.NewBeanRecords(q.bean, qb)
	if err = res.List(q.queryAnd...); err != nil {
		return
	}
	q.result = res
	return
}

func NewRequest(bean interface{}, queryAndString ...string) gin.HandlerFunc {
	var qb = &Request{bean: bean, queryAnd: queryAndString}
	return qb.request
}
